home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 8
/
Aminet 8 (1995)(GTI - Schatztruhe)[!][Oct 1995].iso
/
Aminet
/
util
/
misc
/
ClipHan_1_1.lha
/
Src
/
clip-handler.c
Wrap
C/C++ Source or Header
|
1995-07-09
|
11KB
|
390 lines
/*
** clip-handler.c
** DOS handler for Clipboard access
** Copyright © 1995 Michael Letowski
*/
#define __USE_SYSBASE
#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/filehandler.h>
#include <libraries/iffparse.h>
#include <devices/clipboard.h>
#include <support/types.h>
#include <support/exec.h>
#include <support/dos.h>
#include <string.h>
#include <stdlib.h>
#include <proto/exec.h>
#include <proto/iffparse.h>
#include "clip-handler.rev.h"
#define DOS_NAME "dos.library"
#define DOS_VERN 37L
#define IFFP_NAME "iffparse.library"
#define IFFP_VERN 37L
#define CLIP_NAME "clipboard.device"
STATIC CONST TEXT VersionString[]=
VERSION(PROG_NAME,PROG_VERSION,PROG_REVISION,PROG_DATE);
#define ID_FTXT MAKE_ID('F','T','X','T')
#define ID_CHRS MAKE_ID('C','H','R','S')
#define PATH_SIZE 256
#define SetPktRes(pkt,res1,res2) ((pkt)->dp_Res1=(res1),(pkt)->dp_Res2=(res2))
/* Library bases */
struct ExecBase *SysBase;
struct Library *IFFParseBase;
/* Packet routines */
STATIC struct DosPacket *WaitPacket(struct MsgPort *port);
STATIC VOID ReplyPacket(struct DosPacket *packet, struct MsgPort *port);
STATIC VOID ReplyPacketRes(struct DosPacket *packet, struct MsgPort *port,
LONG res1, LONG res2);
STATIC VOID FlushPackets(struct MsgPort *port);
/* clip-handler routines */
STATIC struct IFFHandle *OpenCH(struct DosPacket *packet);
STATIC VOID CloseCH(struct IFFHandle *iff);
STATIC LONG OpenInputCH(struct DosPacket *packet);
STATIC LONG OpenOutputCH(struct DosPacket *packet);
STATIC LONG OpenUpdateCH(struct DosPacket *packet);
STATIC LONG CloseIOUCH(struct DosPacket *packet);
STATIC VOID ReadClipboard(struct DosPacket *packet);
STATIC VOID WriteClipboard(struct DosPacket *packet);
STATIC VOID SeekClipboard(struct DosPacket *packet);
STATIC LONG IFF2DOS(LONG iffError);
SAVEDS LONG ClipHandler(VOID)
{
struct Library *LocalIFFParseBase;
struct Process *PR;
struct MsgPort *MP,*PacketPort;
struct DosPacket *Pkt;
struct DeviceNode *DevNode;
LBOOL Done=FALSE;
ULONG OpenCount=0;
SysBase=*((struct ExecBase **)4); /* Set up SysBase */
PR=ThisProcessS;
MP=&PR->pr_MsgPort;
if(PR->pr_CLI) /* Run from shell */
return(RETURN_FAIL); /* Failure */
Pkt=WaitPacket(MP); /* Get startup message */
try(DevNode=(struct DeviceNode *)BADDR(Pkt->dp_Arg3),NO_DEV);
/* Open IFFParse */
unless(LocalIFFParseBase=OpenLibrary(IFFP_NAME,IFFP_VERN))
throw2(ReplyPacketRes(Pkt,MP,DOSFALSE,ERROR_INVALID_RESIDENT_LIBRARY), NO_IFFPARSE);
/* Create port */
unless(PacketPort=CreateMsgPort())
throw2(ReplyPacketRes(Pkt,MP,DOSFALSE,ERROR_NO_FREE_STORE), NO_PORT);
/* Set up global bases */
IFFParseBase=LocalIFFParseBase; /* Set up global bases */
DevNode->dn_Task=PacketPort;
Pkt->dp_Arg4=(LONG)PacketPort;
ReplyPacketRes(Pkt,PacketPort,DOSTRUE,Pkt->dp_Res2);
while(!Done)
{
Pkt=WaitPacket(PacketPort);
switch(Pkt->dp_Type)
{
case ACTION_FINDINPUT:
OpenCount+=OpenInputCH(Pkt);
break;
case ACTION_FINDOUTPUT:
OpenCount+=OpenOutputCH(Pkt);
break;
/* case ACTION_FINDUPDATE:
OpenCount+=OpenUpdateCH(Pkt);*/
break;
case ACTION_END:
OpenCount-=CloseIOUCH(Pkt);
break;
case ACTION_READ:
ReadClipboard(Pkt);
break;
case ACTION_WRITE:
WriteClipboard(Pkt);
break;
/* case ACTION_SEEK:
SeekClipboard(Pkt);*/
break;
case ACTION_DIE:
if(OpenCount)
SetPktRes(Pkt,DOSFALSE,ERROR_OBJECT_IN_USE);
else
{
SetPktRes(Pkt,DOSTRUE,0);
Done=TRUE;
}
break;
case ACTION_IS_FILESYSTEM:
SetPktRes(Pkt,DOSFALSE,0);
break;
default:
SetPktRes(Pkt,DOSFALSE,ERROR_ACTION_NOT_KNOWN);
break;
}
ReplyPacket(Pkt,PacketPort);
}
Forbid(); /* Disable task switching */
DevNode->dn_Task=NULL; /* Switch off device */
FlushPackets(PacketPort); /* Discard waiting packets */
UnLoadSeg(DevNode->dn_SegList); /* Unload code */
DevNode->dn_SegList=NULL; /* And mark this fact */
Permit(); /* Enable task switching */
catch(NO_PORT, DeleteMsgPort(PacketPort));
catch(NO_IFFPARSE, CloseLibrary(LocalIFFParseBase));
catch(NO_DEV, );
return(0);
} /* ClipHandler */
STATIC struct DosPacket *WaitPacket(struct MsgPort *port)
{
WaitPort(port);
return((struct DosPacket *)GetMsg(port)->mn_Node.ln_Name);
} /* WaitPacket */
STATIC VOID ReplyPacket(struct DosPacket *packet, struct MsgPort *port)
{
struct MsgPort *ReplyPort=packet->dp_Port;
packet->dp_Port=port;
packet->dp_Link->mn_Node.ln_Name=(STRPTR)packet;
PutMsg(ReplyPort,packet->dp_Link);
} /* ReplyPacket */
STATIC VOID ReplyPacketRes(struct DosPacket *packet, struct MsgPort *port,
LONG res1, LONG res2)
{
SetPktRes(packet,res1,res2);
ReplyPacket(packet,port);
} /* ReplyPacketRes */
STATIC VOID FlushPackets(struct MsgPort *port)
{
struct DosPacket *Packet;
while(Packet=(struct DosPacket *)GetMsg(port)->mn_Node.ln_Name)
ReplyPacketRes(Packet,port,DOSFALSE,ERROR_ACTION_NOT_KNOWN);
} /* FlushPackets */
STATIC struct IFFHandle *OpenCH(struct DosPacket *packet)
{
CHAR Name[PATH_SIZE];
STRPTR Str=(STRPTR)BADDR(packet->dp_Arg3);
struct FileHandle *Handle=FH(packet->dp_Arg1);
struct IFFHandle *IFF;
LONG Unit;
SetPktRes(packet,DOSFALSE,0);
Handle->fh_Arg1=0;
Handle->fh_Port=NULL; /* Non-interactive file */
memcpy(Name,&Str[1],Str[0]); /* Copy data */
Name[Str[0]]='\0'; /* NULL-terminate */
Str=Name;
if(Str=strchr(Str,':')) /* Device name given */
Str++; /* Skip it */
Unit=atol(Str); /* Convert to unit number */
unless(IFF=AllocIFF())
throw2(packet->dp_Res2=ERROR_NO_FREE_STORE, NO_IFF);
unless(IFF->iff_Stream=(ULONG)OpenClipboard(Unit))
throw2(packet->dp_Res2=ERROR_NO_FREE_STORE, NO_CLIPBOARD); /* FIX: error */
InitIFFasClip(IFF);
Handle->fh_Arg1=(LONG)IFF;
packet->dp_Res1=DOSTRUE;
return(IFF);
catch(FOO, );
catch(NO_CLIPBOARD, CloseClipboard((struct ClipboardHandle *)IFF->iff_Stream));
catch(NO_IFF, FreeIFF(IFF));
return(NULL);
} /* OpenCH */
STATIC VOID CloseCH(struct IFFHandle *iff)
{
CloseClipboard((struct ClipboardHandle *)iff->iff_Stream);
FreeIFF(iff);
} /* CloseCH */
STATIC LONG OpenInputCH(struct DosPacket *packet)
{
struct IFFHandle *IFF;
LONG Error;
try(IFF=OpenCH(packet), NO_HANDLE);
try(!(Error=OpenIFF(IFF,IFFF_READ)), NO_IFF);
try(!(Error=StopChunk(IFF,ID_FTXT,ID_CHRS)), IFF_ERROR);
try(!(Error=ParseIFF(IFF,IFFPARSE_SCAN)), IFF_ERROR);
return(1); /* Open succesfull */
catch(IFF_ERROR, );
catch(NO_IFF, CloseIFF(IFF));
SetPktRes(packet,DOSFALSE,IFF2DOS(Error)); /* Set result */
catch(NO_HANDLE, CloseCH(IFF));
return(0); /* Open failed */
} /* OpenInputCH */
STATIC LONG OpenOutputCH(struct DosPacket *packet)
{
struct IFFHandle *IFF;
LONG Error;
try(IFF=OpenCH(packet), NO_HANDLE);
try(!(Error=OpenIFF(IFF,IFFF_WRITE)), NO_IFF);
try(!(Error=PushChunk(IFF,ID_FTXT,ID_FORM,IFFSIZE_UNKNOWN)), IFF_ERROR);
try(!(Error=PushChunk(IFF,0,ID_CHRS,IFFSIZE_UNKNOWN)), IFF_ERROR);
return(1); /* Open succesfull */
catch(IFF_ERROR, );
catch(NO_IFF, CloseIFF(IFF));
SetPktRes(packet,DOSFALSE,IFF2DOS(Error)); /* Set result */
catch(NO_HANDLE, CloseCH(IFF));
return(0); /* Open failed */
} /* OpenOutputCH */
STATIC LONG OpenUpdateCH(struct DosPacket *packet)
{
struct IFFHandle *IFF;
LONG Error;
try(IFF=OpenCH(packet), NO_HANDLE);
try(!(Error=OpenIFF(IFF,IFFF_WRITE)), NO_IFF);
try(!(Error=StopChunk(IFF,ID_FTXT,ID_CHRS)), IFF_ERROR);
/* FIX: Should use write mode here */
try(!(Error=ParseIFF(IFF,IFFPARSE_SCAN)), IFF_ERROR);
return(1); /* Open succesfull */
catch(IFF_ERROR, );
catch(NO_IFF, CloseIFF(IFF));
SetPktRes(packet,DOSFALSE,IFF2DOS(Error)); /* Set result */
catch(NO_HANDLE, CloseCH(IFF));
return(0); /* Open failed */
} /* OpenUpdateCH */
STATIC LONG CloseIOUCH(struct DosPacket *packet)
{
struct IFFHandle *IFF=(struct IFFHandle *)packet->dp_Arg1;
#if 0
/* FIX:??? Check PopChunk() for errors */
if(ftst(IFF->iff_Flags,IFFF_WRITE)) /* Write mode */
if(PopChunk(IFF)==0) /* Close CHRS */
PopChunk(IFF); /* Close FTXT */
#endif
CloseIFF(IFF);
CloseCH(IFF);
SetPktRes(packet,DOSTRUE,0); /* Set result */
return(1);
} /* CloseIOUCH */
STATIC VOID ReadClipboard(struct DosPacket *packet)
{
struct IFFHandle *IFF=(struct IFFHandle *)packet->dp_Arg1;
STRPTR Buffer=(STRPTR)packet->dp_Arg2;
LONG Read=-1,Bytes=packet->dp_Arg3;
SetPktRes(packet,-1,0); /* Set result */
Read=ReadChunkBytes(IFF,Buffer,Bytes); /* Read into buffer */
if(Read<0)
packet->dp_Res2=IFF2DOS(Read);
else
packet->dp_Res1=Read;
} /* ReadClipboard */
STATIC VOID WriteClipboard(struct DosPacket *packet)
{
struct IFFHandle *IFF=(struct IFFHandle *)packet->dp_Arg1;
STRPTR Buffer=(STRPTR)packet->dp_Arg2;
LONG Written=-1,Bytes=packet->dp_Arg3;
SetPktRes(packet,-1,0); /* Set result */
Written=WriteChunkBytes(IFF,Buffer,Bytes); /* Write buffer */
if(Written<0)
packet->dp_Res2=IFF2DOS(Written);
else
packet->dp_Res1=Written;
} /* WriteClipboard */
STATIC VOID SeekClipboard(struct DosPacket *packet)
{
struct IFFHandle *IFF=(struct IFFHandle *)packet->dp_Arg1;
struct ContextNode *CN;
LONG Offset=packet->dp_Arg2,OffsetType=packet->dp_Arg3;
LONG OldPos,NewPos=-1;
SetPktRes(packet,-1,ERROR_SEEK_ERROR); /* Set result */
unless(CN=CurrentChunk(IFF))
return;
unless(CN->cn_Type==ID_FTXT && CN->cn_ID==ID_CHRS)
return;
switch(OffsetType)
{
case OFFSET_BEGINNING:
NewPos=Offset;
break;
case OFFSET_CURRENT:
NewPos=CN->cn_Scan+Offset;
break;
case OFFSET_END:
NewPos=CN->cn_Size-Offset;
break;
}
if(NewPos>0 && NewPos<CN->cn_Size) /* Can seek */
{
OldPos=CN->cn_Scan;
CN->cn_Scan=NewPos;
SetPktRes(packet,OldPos,0);
}
} /* SeekClipboard */
STATIC LONG IFF2DOS(LONG iffError)
{
LONG DOSError=ThisProcessS->pr_Result2;
unless(DOSError) /* Error not set */
switch(iffError)
{
case IFFERR_NOTIFF: DOSError=ERROR_OBJECT_NOT_FOUND; break;
case IFFERR_NOMEM: DOSError=ERROR_NO_FREE_STORE; break;
case IFFERR_SEEK: DOSError=ERROR_SEEK_ERROR; break;
case IFFERR_NOHOOK: DOSError=ERROR_NOT_IMPLEMENTED; break;
default: DOSError=ERROR_OBJECT_WRONG_TYPE; break;
}
return(DOSError);
} /* IFF2DOS */
#if 0
STATIC LONG SeekChunk(struct IFFHandle *iff, LONG offset)
{
struct IFFStreamCmd Cmd=
{
IFFCMD_SEEK, NULL, offset
}; /* Cmd */
return(CallHookPkt((struct Hook *)(iff+1),iff,&Cmd));
} /* SeekChunk */
#endif